package com.lagou.session;


import com.lagou.config.BoundSql;
import com.lagou.handler.*;
import com.lagou.pojo.Configuration;
import com.lagou.pojo.MappedStatement;
import com.lagou.transaction.Transaction;

import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;

public class SimpleExecutor implements  Executor {

    protected Transaction transaction;
    private boolean closed;

    public SimpleExecutor(Transaction transaction) {
        this.transaction = transaction;
    }

    @Override
    public <E> List<E> query(Configuration configuration, ResultSetHandler resultHandler, MappedStatement mappedStatement, Object parameter) throws Exception {
        Statement stmt = null;

        List list;
        try {
            stmt = this.getPreparedStatement(configuration,mappedStatement,parameter);
            StatementHandler handler = new PreparedStatementHandler();
            list = handler.query(stmt, resultHandler);
        } finally {
            this.closeStatement(stmt);
        }

        return list;
    }

    @Override
    public int update(Configuration configuration,MappedStatement mappedStatement, Object parameter) throws Exception {
        Statement stmt = null;
        int i;
        try {
            stmt = this.getPreparedStatement(configuration,mappedStatement,parameter);
            StatementHandler handler = new PreparedStatementHandler();
            i = handler.update(stmt);
        } finally {
            this.closeStatement(stmt);
        }
        return i;
    }

    @Override
    public void commit(boolean required) throws SQLException {
        if (this.closed) {
            System.out.println("Cannot commit, transaction is already closed");
        } else {
            if (required) {
                this.transaction.commit();
            }

        }
    }

    @Override
    public void rollback(boolean required) throws SQLException {
        if (!this.closed) {
            if (required) {
                this.transaction.rollback();
            }
        }
    }

    @Override
    public void close(boolean forceRollback) {
        try {
            try {
                this.rollback(forceRollback);
            } finally {
                if (this.transaction != null) {
                    this.transaction.close();
                }

            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            this.transaction = null;
            this.closed = true;
        }
    }

    @Override
    public Transaction getTransaction(){
        if (this.closed) {
            System.out.println("Executor was closed.");
        }
        return this.transaction;
    }


    private PreparedStatement getPreparedStatement(Configuration configuration, MappedStatement mappedStatement, Object parameter) throws Exception {
        BoundSql boundSql = mappedStatement.getBoundSql(mappedStatement);

        // 3.获取预处理对象：preparedStatement
        PreparedStatement preparedStatement = this.transaction.getConnection().prepareStatement(boundSql.getSqlText());

        ParameterHandler parameterHandler = new DefaultParameterHandler(mappedStatement,parameter,boundSql);

        parameterHandler.setParameters(preparedStatement);//设置参数
        return preparedStatement;
    }


    protected void closeStatement(Statement statement) {
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException var3) {
            }
        }

    }

}
